#include <sys/mman.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <sys/time.h>
#include <string.h>

#include "base_api.h"

#include "cim144.h"
inline int Align8(int x){
	return (x & 0x7==0)? x : ((x & 0xfffffff8) +8);
}
inline int Align8_(int x){
	return (x & 0x7==0)? x : (x & 0xfffffff8);
}

void WriteReg(uint64_t addr ,uint64_t value){
    ROCC_initreg(addr,value);
    //printf("addr 0x%x: value %d\n",addr,value);
    return ;
}
int SelectChip(uint64_t ChipNum){
    uint64_t num = ChipNum+1;
    WriteReg(0x99,num);
    //printf("chipnum is %d\n",ChipNum);
    return 0;
}
void Initdev(){
    WriteReg(0x0f,0x0f);   
    return;
}
void rocc_config(uint32_t random,uint32_t wisenum,uint32_t outshift,uint32_t cimshift){
    uint64_t config_value = (random<<23) |(wisenum<<16)|(outshift<<8)|(cimshift);
    ROCC_config(config_value);
    return;
}
void rocc_push(int8_t* data_in,uint32_t push_start,uint32_t push_num){
    // uint32_t push_start = Align8_(mvm_row_start);
    // uint32_t push_num   = Align8(mvm_row_start+ mvm_row_num) - push_start;
    uint64_t push_value = (push_start<<11)|push_num;
//	printf("push  %d %d\n",push_start,push_num);
//	printf("data %d %d\n",data_in[25],data_in[26]);

    ROCC_push((int64_t)data_in,push_value);
    return;
}
void rocc_mvm(uint32_t array_index,uint32_t mvm_row_start,uint32_t mvm_row_num,
              uint32_t mvm_col_start,uint32_t mvm_col_num){
    uint64_t mvm_rs1 = (mvm_row_num<<16)|mvm_col_num;
    uint64_t mvm_rs2 = (array_index<<22)|(mvm_row_start<<11)|mvm_col_start;
//	printf("mvm %d %lx %lx\n",array_index,mvm_rs1,mvm_rs2);
    ROCC_mvm(mvm_rs1,mvm_rs2);
    return;
}
void rocc_save(int8_t* data_out,uint32_t save_start,uint32_t save_num){
    // uint32_t save_start = Align8_(mvm_col_start);
    // uint32_t save_num   = Align8(mvm_col_start+ mvm_col_num) - save_start;
    // uint32_t save_front = mvm_col_start - save_start;
    uint64_t save_value = (save_start<<11)|save_num;


    ROCC_save((int64_t)data_out,save_value);
//	for(int i =0;i<save_num;i++){
//		printf("%d ",data_out[i]);
//	}
	
}

// void cim_mlp(int8_t* data_in,uint32_t array_index,
//             uint32_t random,uint32_t wisenum,uint32_t outshift,uint32_t cimshift,
//             uint32_t mvm_row_start,uint32_t mvm_row_num,uint32_t mvm_col_start,uint32_t mvm_col_num){
//     uint32_t push_start = Align8_(mvm_row_start);
//     uint32_t push_front = mvm_row_start - push_start;
//     uint32_t push_num   = Align8(mvm_row_start+ mvm_row_num) - push_start;

//     uint32_t save_start = Align8_(mvm_col_start);
//     uint32_t save_front = mvm_col_start - save_start;
//     uint32_t save_num   = Align8(mvm_col_start+ mvm_col_num) - save_start;

//     rocc_config(random,wisenum,outshift,cimshift);
//     rocc_push(data_in,push_start,push_num);
//     rocc_mvm(mvm_row_start,mvm_row_num,mvm_col_start,mvm_col_num,array_index);
//     rocc_save(data_out,save_start,save_num);
// }
